@tool
@icon("../icons/compound_state.svg")
class_name State_Compound
extends State

#region 属性
@onready var _init_state:State = get_node_or_null(init_state)
var _active_state:State = null
var _history_states:Array[State_History] = []
var _needs_deep_history:bool = false
#endregion
#region 字段
@export_node_path("State") var init_state:NodePath:
	get:
		return init_state
	set(value):
		init_state = value
		update_configuration_warnings()
#endregion
#region 信号
signal child_state_entered()
signal child_state_exited()
#endregion

#region 基类方法
## 初始化
func init():
	super()
	for child in get_children():
		if child is State_History:
			var state = child as State_History
			_history_states.append(state)
			_needs_deep_history = _needs_deep_history or state.deep
	for child in get_children():
		if child is State:
			var state = child as State
			state.init()
			state.state_entered.connect(
				func():child_state_entered.emit()
			)
			state.state_exited.connect(
				func():child_state_exited.emit()
			)
## enter
func enter(expect_transition:bool = false):
	super()
	if not expect_transition and not is_instance_valid(_active_state) and active:
		if _init_state:
			if _init_state is State_History:
				_restore_history_state(_init_state)
			else:
				_active_state = _init_state
				_active_state.enter()
	else:
		push_error("没有设置init_state")
# exit
func exit():
	if _history_states.size() > 0:
		var saved_state = SavedState.new()
		save(saved_state,-1 if _needs_deep_history else 1)
		for state in _history_states:
			state.history = saved_state
	if _active_state:
		_active_state.exit()
		_active_state = null
	super()
# save
func save(saved_state:SavedState,child_levels:int = -1):
	super(saved_state,child_levels)
	var parent = saved_state.get_substate_or_null(self)
	if not parent:
		push_error("该State可能没有被保存")
		return
	for state in _history_states:
		state.save(parent,child_levels)
# restore
func restore(saved_state:SavedState,child_levels:int = -1):
	super(saved_state,child_levels)
	if active:
		for child in get_children():
			if child is State and child.active:
				_active_state = child
				break
func handle_transition(transition:Transition,source:State):
	var target = transition.resolve_target()
	if target is not State:
		push_error("转换的目标不是State类型")
		return
	if target == self:
		exit()
		enter(false)
		return
	if target in get_children():
		if is_instance_valid(_active_state):
			_active_state.exit()
		if target is State_History:
			_restore_history_state(target)
			return
		_active_state = target
		_active_state.enter()
		return
	if self.is_ancestor_of(target):
		for child in get_children():
			if child is State and child.is_ancestor_of(target):
				if _active_state != child:
					if is_instance_valid(_active_state):
						_active_state.exit()
					_active_state = child
					_active_state.enter(true)
				child.handle_transition(transition,source)
				return
		return
	get_parent().handle_transition(transition,source)
func step():
	super()
	if _active_state:
		_active_state.step()
## 处理所有转换，如果property_change为true，只处理没有event的转换（无event转换和自动转换）
func process_transitions(event:StringName,property_change:bool = false) -> bool:
	if not active:
		return false
	if is_instance_valid(_active_state):
		if _active_state.process_transitions(event,property_change):
			if not property_change:
				self.event_received.emit(event)
			return true
	return super(event,property_change)
#endregion
#region 公共方法
#endregion
#region 私有方法
func _restore_history_state(target:State_History):
	var saved_state = target.history
	if saved_state:
		restore(saved_state,-1 if target.deep else 1)
		return
	var default_state = target.get_node_or_null(target.default_state)
	if is_instance_valid(default_state):
		_active_state = default_state
		_active_state.enter()
		return
	else:
		push_error("State_History中的默认State找不到")
		return
#endregion
#region 生命周期函数
func _init() -> void:
	if Engine.is_editor_hint():
		child_entered_tree.connect(func(child:Node):
			if child is State and init_state.is_empty():
				(func ():init_state = get_path_to(child)).call_deferred()
		)
func _get_configuration_warnings() -> PackedStringArray:
	var warnings = super._get_configuration_warnings()
	var child_count = 0
	for child in get_children():
		if child is State:
			child_count += 1
	if child_count < 1:
		warnings.append("State_Compound至少需要两个子State")
	elif child_count < 2:
		warnings.append("State_Compound只有一个子State，没有使用State_Compound的必要")
	var the_initial_state = get_node_or_null(init_state)
	if not is_instance_valid(the_initial_state):
		warnings.append("初始节点没找到，请检查路径")
	elif the_initial_state.get_parent() != self:
		warnings.append("初始节点必须是该State_Compound的子节点")
	return warnings
#endregion
